// import XLSX from 'xlsx'
// import * as XLSX from 'xlsx'
import _ from 'lodash'
// import { ElLoading } from 'element-plus'
 
/**
 * Author: vinny
 * Date: 2024-09-01 10:15:32
 * version:
 * Des: 公用数据处理js方法
 */
// let elLoading = null
let utils = {
  // loading: () => {
  //   const show = () => {
  //     if (localStorage.getItem('token') === null) return
  //     elLoading = ElLoading.service({
  //       lock: true,
  //       text: '加载中',
  //       background: 'rgba(0, 0, 0, 0.3)',
  //       customClass: 'z9999'
  //     })
  //   }
  //   const hide = () => {
  //     elLoading?.close()
  //   }
  //   return { show, hide }
  // },
  // 时间格式化
  formatDate: (date, fmt) => {
    if (date == null) {
      return ''
    }
    let t = new Date(date)
    let tf = function (i) {
      return (i < 10 ? '0' : '') + i
    }
    return fmt.replace(/yyyy|MM|dd|HH|mm|ss/g, function (a) {
      switch (a) {
        case 'yyyy':
          return tf(t.getFullYear())
        case 'MM':
          return tf(t.getMonth() + 1)
        case 'mm':
          return tf(t.getMinutes())
        case 'dd':
          return tf(t.getDate())
        case 'HH':
          return tf(t.getHours())
        case 'ss':
          return tf(t.getSeconds())
      }
    })
  },
  // 获取当前时间格式化yyyy-mm-dd HH:mm:ss
  getTime(date = new Date()) {
    let y = date.getFullYear()
    let m = date.getMonth() + 1
    m = m < 10 ? '0' + m : m
    let d = date.getDate()
    d = d < 10 ? '0' + d : d
    let h = date.getHours()
    h = h < 10 ? '0' + h : h
    let minute = date.getMinutes()
    minute = minute < 10 ? '0' + minute : minute
    let second = date.getSeconds()
    second = second < 10 ? '0' + second : second
    return y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second
  },
  // 获取自然日-始
  startNatureday: () => {
    let date1 = new Date(new Date(new Date().toLocaleDateString()).getTime())
    let startTime =
      date1.getFullYear() +
      '-' +
      (date1.getMonth() + 1 < 10 ? '0' + (date1.getMonth() + 1) : date1.getMonth() + 1) +
      '-' +
      (date1.getDate() < 10 ? '0' + date1.getDate() : date1.getDate()) +
      ' ' +
      (date1.getHours() < 10 ? '0' + date1.getHours() : date1.getHours()) +
      ':' +
      (date1.getMinutes() < 10 ? '0' + date1.getMinutes() : date1.getMinutes()) +
      ':' +
      (date1.getSeconds() < 10 ? '0' + date1.getSeconds() : date1.getSeconds())
    return startTime
  },
  // 获取自然日-末
  endNatureday: () => {
    let date2 = new Date(new Date(new Date().toLocaleDateString()).getTime() + 24 * 60 * 60 * 1000 - 1)
    let endTime =
      date2.getFullYear() +
      '-' +
      (date2.getMonth() + 1) +
      '-' +
      date2.getDate() +
      ' ' +
      date2.getHours() +
      ':' +
      date2.getMinutes() +
      ':' +
      date2.getSeconds()
    return endTime
  },

  /**
   * 千分位
   */
  fmoney: (s, n = 2) => {
    if (!s) s = 0
    // let n = 4
    n = n > 0 && n <= 20 ? n : 2
    // eslint-disable-next-line no-useless-escape
    s = parseFloat((s + '').replace(/[^\d\.-]/g, '')).toFixed(n) + ''
    // eslint-disable-next-line one-let
    let l = s.split('.')[0].split('').reverse(),
      r = s.split('.')[1]
    let t = ''
    for (let i = 0; i < l.length; i++) {
      t += l[i] + ((i + 1) % 3 === 0 && i + 1 !== l.length ? ',' : '')
    }
     
    if(Number(s) ===0){return '0'}
    return t.split('').reverse().join('') + '.' + r
  },
  formatNumber(num) {
    // 先转为整数（避免原数字带小数），再格式化千分位
    return Math.floor(num).toLocaleString('zh-CN', {
      maximumFractionDigits: 0 // 不保留小数
    });
  },
  // 两个浮点数相加
  AddFun: (num1, num2) => {
    let r1, r2, m
    try {
      r1 = num1.toString().split('.')[1].length
    } catch (e) {
      r1 = 0
    }
    try {
      r2 = num2.toString().split('.')[1].length
    } catch (e) {
      r2 = 0
    }
    m = Math.pow(10, Math.max(r1, r2))
    // return (num1*m+num2*m)/m;
    return Math.round(num1 * m + num2 * m) / m
  },
  // 两个浮点数相减
  SubFun: (num1, num2) => {
    let r1, r2, m, n
    try {
      r1 = num1.toString().split('.')[1].length
    } catch (e) {
      r1 = 0
    }
    try {
      r2 = num2.toString().split('.')[1].length
    } catch (e) {
      r2 = 0
    }
    m = Math.pow(10, Math.max(r1, r2))
    n = r1 >= r2 ? r1 : r2
    return (Math.round(num1 * m - num2 * m) / m).toFixed(n)
  },
  // 两数相除
  DivFun: (num1, num2) => {
    let t1, t2, r1, r2
    try {
      t1 = num1.toString().split('.')[1].length
    } catch (e) {
      t1 = 0
    }
    try {
      t2 = num2.toString().split('.')[1].length
    } catch (e) {
      t2 = 0
    }
    r1 = Number(num1.toString().replace('.', ''))
    r2 = Number(num2.toString().replace('.', ''))
    return (r1 / r2) * Math.pow(10, t2 - t1)
  },
  // 两数相乘
  MulFun: (num1, num2) => {
    // eslint-disable-next-line one-let

    let m = 0,
      s1 = num1.toString(),
      s2 = num2.toString()
    try {
      m += s1.split('.')[1].length
    } catch (e) {
      console.log(e)
    }
    try {
      m += s2.split('.')[1].length
    } catch (e) {
      console.log(e)
    }
    return (Number(s1.replace('.', '')) * Number(s2.replace('.', ''))) / Math.pow(10, m)
  },

  /** *json数组中通过value值获取索引值
   * arr：json数组 let a=[{a:1},{c:1}]
   * json数组检索对象的key值  key=c
   * value检索对象属性值 如 let value=1
   * */
  valueIndex: (arr, key, value) => {
    for (let n in arr) {
      if (arr[n][key] === value) {
        return n
      }
    }
  },
  removeClass: (btnAll, hasClass) => {
    for (let i = 0; i < btnAll.length; i++) {
      if (btnAll[i].classList.value.indexOf(hasClass) >= 0) {
        btnAll[i].classList.remove(hasClass)
      }
    }
  },
  // removeClass2: (btnAll, hasClass, activeClass) => {
  //   for (let i = 0; i < btnAll.length; i++) {
  //     if (btnAll[i].classList.value.indexOf(hasClass) >= 0) {
  //       btnAll[i].classList.remove(activeClass)
  //     }
  //   }
  // },
  addClass: (el, addClass) => {
    el.$el.className += ' ' + addClass
  },
  /**
   * 选中效果且不删除兄弟元素
   *  el :点击对象元素
   * ctiveClass：选中对象Class
   */
  selfActive: (el, activeClass) => {
    let index = el.$el.className.indexOf(activeClass)
    if (index >= 0) {
      el.$el.className = el.$el.className.substring(0, index)
    } else {
      utils.addClass(el, activeClass)
    }
  },
  /** * 选中效果且删除兄弟元素
   * el :点击对象元素
   * activeEl： 所有点击对象元素
   * activeClass：选中对象Class
   * hasClass : 用于筛选自己需要删除的元素
   * 添加回调
   * 删除回调
   */
  active: (el, activeEl, activeClass, hasClass, addCallback, removeCallback) => {
    let btnAll = el.$el.parentNode.getElementsByTagName(activeEl)
    let index = el.$el.className.indexOf(activeClass)
    if (index >= 0) {
      el.$el.className = el.$el.className.substring(0, index)
      // eslint-disable-next-line no-unused-expressions
      removeCallback ? removeCallback(el, btnAll) : ''
    } else {
      utils.removeClass(btnAll, hasClass, activeClass)
      utils.addClass(el, activeClass)
      if (addCallback) {
        addCallback(el, btnAll)
      }
    }
  },
  /**
   * 数组去空
   * arr: 数组
   *  */
  removeEmptyArrayEle: (arr) => {
    for (let i = 0; i < arr.length; i++) {
      if (!arr[i] || arr[i] === undefined || arr[i].length === 0) {
        arr.splice(i, 1)
        i = i - 1 // i - 1 ,因为空元素在数组下标 2 位置，删除空之后，后面的元素位置，删除空之后，后面的元素要向前补位，
        // 这样才能真正去掉空元素,觉得这句可以删掉的连续为空试试，然后思考其中逻辑
      }
    }
    return arr
  },
  /***
   * json 转换为字符串拼接方式
   */
  jsonStr: (arr) => {
    let txt = ''
    for (let item in arr) {
      if (item && (arr[item] !== '' || arr[item] !== null)) {
        txt += item + '=' + arr[item] + '&'
      }
    }
    txt = txt.substr(0, txt.length - 1)
    return txt
  },
  /**
   * 获取select 选中的label值
   * @param {*} arrs  select 列表数组
   * @param {*} selectVal   select 选中的值
   * @param {*} value select 选中的value值绑定 字段
   * @param {*} label select 选中的label值绑定 字段
   */
  selectLabel(arrs, selectVal, value, label) {
    let arr = []
    arr = arrs
    let obj = {}
    obj = arr.find((item) => {
      return item[value] === selectVal // 比如：选项2
    })
    if (obj !== '' && obj !== undefined) {
      return obj[label] // 获取label的值 0-2000
    }
  },
  /**
   * 为数组添加指定空数据长度
   * @param {*} arr 数组
   * @param {*} length 长度
   */
  addEmptyData(arr, length) {
    // console.log(arr)
    // 20190114 修改i<length   为i<6
    for (let i = 0; i < 6; i++) {
      for (let j = arr[i].length; arr[i].length < length; j++) {
        arr[i][j] = ''
      }
    }
    // 返回显示数组
    // console.log(arr)
    return arr
  },
  /**
   * 手动计算合计
   * @param {*} arr 数组
   * @param {*} labelArr 需要计算合计字段对象数组
   */
  handSum(arr, labelArr) {
    let rt = {}
    for (let i = 0; i < labelArr.length; i++) {
      rt[labelArr[i]] = ''
      for (let j = 0; j < arr.length; j++) {
        // eslint-disable-next-line no-prototype-builtins
        if (arr[j].hasOwnProperty(labelArr[i])) {
          rt[labelArr[i]] = utils.AddFun(rt[labelArr[i]], arr[j][labelArr[i]] || 0)
        } else {
          console.warn(labelArr[i] + '字段不存在！')
        }
      }
    }
    return rt
  },
  /**
   *删除对象中特定字段
   * @param {*} param 对象
   * @param {*} arr 字段数组
   */
  deleteLabel(param, arr) {
    for (let item in arr) {
      if (param) {
        delete param[arr[item]]
      } else {
        console.warn('deleteLabel函数参数parma对象不存在')
      }
    }
    return param
  },
  /**
   *获取cookie
   * @param {*} name
   * @returns
   */
  getCookie(name) {
    let arr = null
    let reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)')
    // eslint-disable-next-line no-cond-assign
    if ((arr = document.cookie.match(reg))) {
      return arr[2]
    } else {
      return null
    }
  },
  /**
   *设置cookie,增加到vue实例方便全局调用
   * @param {*} cname
   * @param {*} value
   * @param {*} expiredays 过期时间
   */
  setCookie(cname, value, expiredays = null, path = null) {
    let exdate = new Date()
    exdate.setDate(exdate.getDate() + expiredays)
    document.cookie =
      cname +
      '=' +
      escape(value) +
      (path ? ';path=' + path : ';path=/') +
      (expiredays == null ? '' : ';expires=' + exdate.toGMTString()) +
      (process.env.NODE_ENV === 'development' ? '' : ';domain=.ccynice.com')
  },
  /**
   *删除cookie
   * @param {*} name
   */
  delCookie(name) {
    let exp = new Date()
    exp.setTime(exp.getTime() - 1)
    let cval = utils.getCookie(name)
    if (cval != null) {
      document.cookie = name + '=' + cval + ';domain=.fuxintianxia.com;expires=' + exp.toGMTString()
      if (process.env.NODE_ENV === 'development') {
        document.cookie = name + '=' + cval + ';expires=' + exp.toGMTString()
      }
    }
  },
  /**
   *金额大写转换
   */
  DX(n) {
    // n
    if (!/^(0|[1-9]\d*)(\.\d+)?$/.test(n)) {
      return '数据非法'
    }
    let unit = '千百拾亿千百拾万千百拾元角分'
    let str = ''
    n += '00'
    let p = n.indexOf('.')
    if (p >= 0) {
      n = n.substring(0, p) + n.substr(p + 1, 2)
    }
    unit = unit.substr(unit.length - n.length)
    for (let i = 0; i < n.length; i++) {
      str += '零壹贰叁肆伍陆柒捌玖'.charAt(n.charAt(i)) + unit.charAt(i)
    }
    return str
      .replace(/零(千|百|拾|角)/g, '零')
      .replace(/(零)+/g, '零')
      .replace(/零(万|亿|元)/g, '$1')
      .replace(/(亿)万|壹(拾)/g, '$1$2')
      .replace(/^元零?|零分/g, '')
      .replace(/元$/g, '元整')
  },
  /**
   *数字转换金额格式化
   *设置type 不带小数位(默认是有小数位)
   */
  formatMoney(s, type) {
    s = s * 10000
    // eslint-disable-next-line no-useless-escape
    if (/[^0-9\.]/.test(s)) {
      return '0'
    }
    if (s == null || s === '') {
      return '0'
    }
    s = s.toString().replace(/^(\d*)$/, '$1.')
    s = (s + '00').replace(/(\d*\.\d\d)\d*/, '$1')
    s = s.replace('.', ',')
    let re = /(\d)(\d{3},)/
    while (re.test(s)) {
      s = s.replace(re, '$1,$2')
    }
    s = s.replace(/,(\d\d)$/, '.$1')
    if (type === 0) {
      let a = s.split('.')
      if (a[1] === '00') {
        s = a[0]
      }
    }
    return s + ' 元'
  },
  /*
   *打印时间拆分
   */
  splitTime(time) {
    // eslint-disable-next-line no-useless-escape
    let timearr = time.replace(' ', ':').replace(/\:/g, '-').split('-')
    return timearr
  },
  Throttle(fn, t) {
    let last
    let timer
    let interval = t || 500
    return function () {
      let args = arguments
      let now = +new Date()
      if (last && now - last < interval) {
        clearTimeout(timer)
        timer = setTimeout(() => {
          last = now
          fn.apply(this, args)
        }, interval)
      } else {
        last = now
        fn.apply(this, args)
      }
    }
  },
  isEmpty(val) {
    if (val && val.length > 0) {
      return false
    } else {
      return true
    }
  },
  /**
   * 日期解析，字符串转日期
   * @param dateString 可以为2017-02-16，2017/02/16，2017.02.16
   * @returns {Date} 返回对应的日期对象
   */
  dateParse(dateString) {
     
    let SEPARATOR_BAR = '-'
    let SEPARATOR_SLASH = '/'
    let SEPARATOR_DOT = '.'
    let dateArray
    if (dateString.indexOf(SEPARATOR_BAR) > -1) {
      dateArray = dateString.split(SEPARATOR_BAR)
    } else if (dateString.indexOf(SEPARATOR_SLASH) > -1) {
      dateArray = dateString.split(SEPARATOR_SLASH)
    } else {
      dateArray = dateString.split(SEPARATOR_DOT)
    }
    return new Date(dateArray[0], dateArray[1] - 1, dateArray[2])
  },

  /**
   * 日期时间比较大小
   * compareDateString大于dateString，返回1；
   * 等于返回0；
   * compareDateString小于dateString，返回-1
   * @param dateString 日期 yyyy-MM-dd
   * @param compareDateString 比较的日期 yyyy-MM-dd
   */
  dateTimeCompare(dateString, compareDateString) {
    if (utils.isEmpty(dateString)) {
      console.warn('dateString不能为空')
      return
    }
    if (utils.isEmpty(compareDateString)) {
      console.warn('compareDateString不能为空')
      return
    }
    // eslint-disable-next-line no-useless-escape
    let dateTime = new Date(dateString.replace(/\-/g, '/')).getTime()
    // let compareDateTime = utils.dateParse(compareDateString).getTime()
    // eslint-disable-next-line no-useless-escape
    let compareDateTime = new Date(compareDateString.replace(/\-/g, '/')).getTime()
    if (compareDateTime > dateTime) {
      return 1
    } else if (compareDateTime === dateTime) {
      return 0
    } else {
      return -1
    }
  },
  /**
   * 日期比较大小
   * compareDateString大于dateString，返回1；
   * 等于返回0；
   * compareDateString小于dateString，返回-1
   * @param dateString 日期
   * @param compareDateString 比较的日期
   */
  dateCompare(dateString, compareDateString) {
     
    if (utils.isEmpty(dateString)) {
      console.warn('dateString不能为空')
      return
    }
    if (utils.isEmpty(compareDateString)) {
      console.warn('compareDateString不能为空')
      return
    }
     
    let dateTime = utils.dateParse(dateString).getTime()
    let compareDateTime = utils.dateParse(compareDateString).getTime()
    if (compareDateTime > dateTime) {
      return 1
    } else if (compareDateTime === dateTime) {
      return 0
    } else {
      return -1
    }
  },

  /**
   * 判断日期是否在区间内，在区间内返回true，否返回false
   * @param dateString 日期字符串
   * @param startDateString 区间开始日期字符串
   * @param endDateString 区间结束日期字符串
   * @returns {Number}
   */
  isDateBetween(dateString, startDateString, endDateString) {
    if (utils.isEmpty(dateString)) {
      console.warn('dateString不能为空')
      return
    }
    if (utils.isEmpty(startDateString)) {
      console.warn('startDateString不能为空')
      return
    }
    if (utils.isEmpty(endDateString)) {
      console.warn('endDateString不能为空')
      return
    }
    let flag = false
    let startFlag = utils.dateCompare(dateString, startDateString) < 1
    let endFlag = utils.dateCompare(dateString, endDateString) > -1
    if (startFlag && endFlag) {
      flag = true
    }
    return flag
  },

  /**
   * 判断日期区间[startDateCompareString,endDateCompareString]是否完全在别的日期区间内[startDateString,endDateString]
   * 即[startDateString,endDateString]区间是否完全包含了[startDateCompareString,endDateCompareString]区间
   * 在区间内返回true，否返回false
   * @param startDateString 新选择的开始日期，如输入框的开始日期
   * @param endDateString 新选择的结束日期，如输入框的结束日期
   * @param startDateCompareString 比较的开始日期
   * @param endDateCompareString 比较的结束日期
   * @returns {Boolean}
   */
  isDatesBetween(startDateString, endDateString, startDateCompareString, endDateCompareString) {
    if (utils.isEmpty(startDateString)) {
      console.warn('startDateString不能为空')
      return
    }
    if (utils.isEmpty(endDateString)) {
      console.warn('endDateString不能为空')
      return
    }
    if (utils.isEmpty(startDateCompareString)) {
      console.warn('startDateCompareString不能为空')
      return
    }
    if (utils.isEmpty(endDateCompareString)) {
      console.warn('endDateCompareString不能为空')
      return
    }
    let flag = false
    let startFlag = utils.dateCompare(startDateCompareString, startDateString) < 1
    let endFlag = utils.dateCompare(endDateCompareString, endDateString) > -1
    if (startFlag && endFlag) {
      flag = true
    }
    return flag
  },
  // 手机号码脱敏
  geTel(tel) {
    var reg = /^(\d{3})\d{4}(\d{4})$/
    return tel.replace(reg, '$1****$2')
  },
  // 手机
  isPhone(rules, value, callback) {
    let el = /^1[3|4|6|7|5|8|9][0-9]\d{8}$/.test(value)
    if (!value) {
      callback(new Error('请输入手机号码'))
    } else if (!el) {
      callback(new Error('手机号不符合规范'))
    } else {
      callback()
    }
  },
  // 固话验证
  telephone(rules, value, callback) {
    let el = !/^(\(\d{3,4}\)|\d{3,4}-|\s)?\d{7,14}$/.test(value)
    if (value === '') {
      callback(new Error('电话号码不能为空'))
    } else if (!el) {
      callback(new Error('电话号码格式不正确'))
    } else {
      callback()
    }
  },
  // 手机号或者固定电话  jxh
  isPhoneOrTelephone(rules, value, callback) {
    let el = !/^(\(\d{3,4}\)|\d{3,4}(-|\s)?)?\d{7,11}$/.test(value) && !/^1[3|4|7|5|6|8][0-9]\d{8}$/.test(value)
    if (value === '') {
      callback(new Error('电话号码不能为空'))
    } else if (el) {
      callback(new Error('电话号码格式不正确'))
    } else {
      callback()
    }
  },
  // 中文
  isChinese(value) {
    return /[\u4e00-\u9fa5]/.test(value)
  },
  // 中文姓名
  isChineseUser(value) {
    return /[^\u4E00-\u9FA5]/g.test(value)
  },
  // 全数字
  isNum(value) {
    return /^[0-9]\d*$/.test(value)
  },
  // 全英文
  isEng(value) {
    return /^[a-zA-Z]*$/.test(value)
  },
  // 英文数字
  isEngNum(value) {
    return /^[a-zA-Z0-9]+$/.test(value)
  },
  // 必须英文+数字
  mustEngNum(value) {
    return /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z]{8,20}$/.test(value)
  },
  // 身份证
  isIdCard(value) {
    return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(value.toUpperCase())
  },
  // 英文、数字、汉字
  isEngNumCh(value) {
    return /^[a-zA-Z0-9\u4E00-\u9FA5]+$/.test(value)
  },
  // 用户名
  isUserName(rules, value, callback) {
    let el = utils.isEngNum(value)
    if (!value) {
      callback(new Error('请输入用户名'))
    } else if (!el) {
      callback(new Error('不超过20个字符，仅支持英文和数字'))
    } else {
      callback()
    }
  },
  //代理商用户名
  isAgentUserNo(rules, value, callback) {
    let el = utils.isEngNum(value)
    if (!value) {
      callback(new Error('请输入用户名'))
    } else if (!el) {
      callback(new Error('不超过20个字符，仅支持英文和数字'))
    } else {
      callback()
    }
  },
  //代理商名称
  isAgentUserName(rules, value, callback) {
    let el = utils.isEngNumCh(value)
    if (!value) {
      callback(new Error('请输入名称'))
    } else if (!el) {
      callback(new Error('不超过20个字符，仅支持中英文数字字符'))
    } else {
      callback()
    }
  },
  // 英文、数字、下划线
  isNickName(rules, value, callback) {
    let el = utils.isEngNumCh(value)
    if (!value) {
      callback(new Error('请输入姓名'))
    } else if (!el) {
      callback(new Error('不超过20个字符，仅支持中英文和数字'))
    } else {
      callback()
    }
  },
  // 数量
  quantityCeiling(rules, value, callback) {
    let el = utils.isNum(value)
    if (!value) {
      callback(new Error('请输入数量'))
    } else if (value > 100000) {
      callback(new Error('支持最高上限为：100000'))
    } else if (!el || value === '0') {
      callback(new Error('仅支持正整数'))
    } else {
      callback()
    }
  },

  // 8-20 数字加字母
  isPwd(rules, value, callback) {
    let el = /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z]{8,20}$/.test(value)
    if (!value) {
      callback(new Error('请输入密码'))
    } else if (!el) {
      callback(new Error('密码为8-20位，必须包含数字和字母'))
    } else {
      callback()
    }
  },

  periodValidity(rules, value, callback) {
    let el = utils.isNum(value)
    if (!value) {
      callback(new Error('请输入有效期'))
    } else if (!el || Number(value) < 1 || Number(value) > 365) {
      callback(new Error('有效期上限为365天，下限为1天'))
      // } else if (!el) {
      //   callback(new Error('有效期上限为365天，下限为1天'))
    } else {
      callback()
    }
  },
  pwd2(rules, value, callback) {
    let el = utils.isPwd02(value)
    if (!value) {
      callback(new Error('密码不能为空'))
    } else if (value.length < 8) {
      callback(new Error('密码长度必须大于8位'))
    } else if (!el) {
      callback(new Error('密码大于8位字母数字组合'))
    } else {
      callback()
    }
  },
  // 字符串转日期格式，strDate要转为日期格式的字符串
  getLocalTime(nS) {
    return new Date(parseInt(nS) * 1000).toLocaleString().substr(0, 17)
  },
  // alert(getLocalTime(1293072805));
  // 整数，小数
  isNumPoint(value) {
    return /^[0-9]+([.]{1}[0-9]+){0,1}$/.test(value)
  },
  // 验证数字，小数，可以为0
  checkIsNumPointZero(rules, value, callback) {
    let el = utils.isNumPoint(value)
    if (!el) {
      callback(new Error())
    } else {
      callback()
    }
  },
  // 充值金额 验证数字，小数，不可以<0
  checkIsNumPoint(rules, value, callback) {
    let el = utils.isNumPoint(value)
    let point = (value + '').split('.')
    if (!value && value !== 0 && value !== '0') {
      callback(new Error('请输入充值金额'))
    } else if (point.length === 2 && point?.[1].length > 2) {
      // ElMessage.error('')
      callback(new Error('充值金额保留两位小数'))
    } else if (Number(value) >= 100000000) {
      callback(new Error('充值金额不能大于1亿元'))
    } else if (!el) {
      callback(new Error('充值金额不能小于等于0元'))
    } else if (value <= 0) {
      callback(new Error('充值金额不能小于等于0元'))
    } else {
      callback()
    }
  },
  checkRefund(rules, value, callback) {
    let el = utils.isNumPoint(value)
    if (!value && value !== 0 && value !== '0') {
      callback(new Error('请输入退款金额'))
    } else if (!el) {
      callback(new Error('退款金额不能小于等于0元'))
    } else if (value <= 0) {
      callback(new Error('退款金额不能小于等于0元'))
    } else {
      callback()
    }
  },
  checkMoney(rules, value, callback) {
    let el = utils.isNumPoint(value)
    if (!value && value !== 0 && value !== '0') {
      callback(new Error('请输入优惠金额'))
    } else if (!el || value <= 0) {
      callback(new Error('请输入优惠金额不能小于等于0元'))
    } else {
      callback()
    }
  },
  // 身份证
  isIdCards(idCard) {
    // 15位和18位身份证号码的正则表达式
    let regIdCard =
      /^(^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$)|(^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])((\d{4})|\d{3}[Xx])$)$/
    // 如果通过该验证，说明身份证格式正确，但准确性还需计算
    if (regIdCard.test(idCard)) {
      if (idCard.length === 18) {
        // eslint-disable-next-line no-array-constructor
        let idCardWi = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2) // 将前17位加权因子保存在数组里
        // eslint-disable-next-line no-array-constructor
        let idCardY = new Array(1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2) // 这是除以11后，可能产生的11位余数、验证码，也保存成数组
        let idCardWiSum = 0 // 用来保存前17位各自乖以加权因子后的总和
        for (let i = 0; i < 17; i++) {
          idCardWiSum += idCard.substring(i, i + 1) * idCardWi[i]
        }
        let idCardMod = idCardWiSum % 11 // 计算出校验码所在数组的位置
        let idCardLast = idCard.substring(17) // 得到最后一位身份证号码
        // 如果等于2，则说明校验码是10，身份证号码最后一位应该是X
        if (idCardMod === 2) {
          if (idCardLast === 'X' || idCardLast === 'x') {
            return true
          } else {
            return false
          }
        } else {
          // 用计算出的验证码与最后一位身份证号码匹配，如果一致，说明通过，否则是无效的身份证号码
          if (idCardLast === idCardY[idCardMod]) {
            return true
          } else {
            return false
          }
        }
      }
    } else {
      return false
    }
    return true
  },
  /**
   * 邮件
   */
  isEmail(rules, value, callback) {
    // eslint-disable-next-line no-useless-escape
    let el =
      /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test(
        value
      )
    if (!value) {
      callback()
    } else if (!el) {
      callback(new Error('邮箱格式不正确'))
    } else {
      callback()
    }
  },
  // /**
  //  * 密码设置确认
  //  * yxf
  //  */
  // password (rule, value, callback) {
  //   let that = store.state.that
  //   if (!value) {
  //     callback(new Error('请输入密码'))
  //   } else if (value.length < 8) {
  //     callback(new Error('密码长度必须大于8'))
  //   } else {
  //     if (that.addForm.checkpwd !== '') {
  //       that.$refs.addForm.validateField('checkPass')
  //     }
  //     callback()
  //   }
  // },
  // checkpwd (rule, value, callback) {
  //   let that = store.state.that
  //   if (!value) {
  //     callback(new Error('请输入确认密码'))
  //   } else if (value.length < 8) {
  //     callback(new Error('密码长度必须大于8'))
  //   } else if (value !== that.addForm.password) {
  //     callback(new Error('两次输入密码不一致!'))
  //   } else {
  //     callback()
  //   }
  // },
  /**
   * 根据数据字典获取指定code数据
   * @param data 数据字典
   * @param codeName 数据字典标时
   * @returns {json}
   */
  dict(data, codeName) {
    let dict = []
    let dictJson = {}
    for (let i = 0; i < data.length; i++) {
      if (data[i].typeCode === codeName && typeof codeName === 'string') {
        dict.push(data[i])
      } else if (typeof codeName === 'object') {
        for (let j = 0; j < codeName.length; j++) {
          if (data[i].typeCode === codeName[j]) {
            if (typeof dictJson[codeName[j]] !== 'object') {
              dictJson[codeName[j]] = []
            }
            dictJson[codeName[j]].push(data[i])
          }
        }
      }
    }
    return typeof codeName === 'string' ? dict : dictJson
  },
  // isCountry: function (rules, value, callback) {
  //   let that = store.state.that
  //   if (!that.$store.state.pro) {
  //     callback(new Error('请选择省！'))
  //   } else if (!that.$store.state.city) {
  //     callback(new Error('请选择市！'))
  //   } else if (!that.$store.state.country && that.$store.state.pro !== '台湾省') {
  //     callback(new Error('请选择区！'))
  //   } else {
  //     callback()
  //   }
  // },
  // 获取前后N天的时间
  getDay: function (day) {
    let today = new Date()

    let targetdayMilliseconds = today.getTime() + 1000 * 60 * 60 * 24 * day

    today.setTime(targetdayMilliseconds) // 注意，这行是关键代码

    let tYear = today.getFullYear()

    let tMonth = today.getMonth()

    let tDate = today.getDate()

    tMonth = utils.doHandleMonth(tMonth + 1)

    tDate = utils.doHandleMonth(tDate)

    return tYear + '-' + tMonth + '-' + tDate
  },
  // 获取上一月的时间最后一天
  getLastMonthLastDay: function () {
    let today = new Date()
    let tYear = today.getFullYear()

    let tMonth = today.getMonth()
    tMonth = tMonth === 0 ? 12 : tMonth

    // let tDate = today.getDate()

    let myDate = new Date(tYear, tMonth, 0)

    return tYear + '-' + tMonth + '-' + myDate.getDate()
  },
  // 获取上一月的时间第一天
  getLastMonthFirstDay: function () {
    let today = new Date()
    let tYear = today.getFullYear()
    let tMonth = today.getMonth()
    tMonth = tMonth === 0 ? 12 : tMonth
    return tYear + '-' + tMonth + '-01'
  },
  doHandleMonth: function (month) {
    let m = month

    if (month.toString().length === 1) {
      m = '0' + month
    }
    return m
  },
  // 回车事件
  keyupSubmit(callback, $el) {
    let el = $el || document.querySelector('.el-form')
    if (el) {
      el.onkeydown = () => {
        let _key = window.event.keyCode
        if (_key === 13) {
          if (callback) {
            callback()
          }
        }
      }
    }
  },
  //  去掉空格
  trim(str) {
    if (str) {
      str = str.replace(/^\s+/, '')
      for (let i = str.length - 1; i >= 0; i--) {
        if (/\S/.test(str.charAt(i))) {
          str = str.substring(0, i + 1)
          break
        }
      }
    }
    return str
  },
  /**
   * json数组去重
   * @param arr json
   * @returns {json}
   */
  jsonUnique(arr) {
    if (arr.length <= 0) {
      return {
        unique: false
      }
    }
    let newVal = new Set()
    let newValJson = new Set()
    arr.map((v) => {
      newVal.add(JSON.stringify(v))
    })
    newValJson = Array.from(newVal)
    newValJson.forEach((item, key) => {
      newValJson[key] = JSON.parse(item)
    })
    // 重复返回false
    if (newVal.size !== arr.length) {
      return {
        newVal: newValJson,
        unique: false
      }
    } else {
      return {
        newVal: newValJson,
        unique: true
      }
    }
  },
  /**
   * 判断两个日期是否在几个月之内
   */
  completeDate(time1, time2, m) {
    let diffyear = time2.getFullYear() - time1.getFullYear()
    let diffmonth = diffyear * 12 + time2.getMonth() - time1.getMonth()
    if (diffmonth < 0) {
      return false
    }

    let diffDay = time2.getDate() - time1.getDate()

    if (diffmonth < m || (diffmonth === m && diffDay <= 0)) {
      if (diffmonth === m && diffDay === 0) {
        let timeA = time1.getHours() * 3600 + 60 * time1.getMinutes() + time1.getSeconds()
        let timeB = time2.getHours() * 3600 + 60 * time2.getMinutes() + time2.getSeconds()
        if (timeB - timeA > 0) {
          return false
        }
      }
      return true
    }
    return false
  },
  /**
   * 获取两个日期之间相差的天数
   */
  getDaysBetween(dateString1, dateString2) {
    let startDate = Date.parse(dateString1)
    let endDate = Date.parse(dateString2)
    let days = (endDate - startDate) / (1 * 24 * 60 * 60 * 1000)
    // alert(days);
    return days
  },
  // 计算两个日期的间隔时间（时间差）精准到时分
  DateDifference(faultDate, completeTime, type) {
    // let d1 = new Date(faultDate);
    // let d2 = new Date(completeTime);
    let stime = new Date(faultDate).getTime()
    let etime = new Date(completeTime).getTime()
    let usedTime = etime - stime // 两个时间戳相差的毫秒数
    let days = Math.floor(usedTime / (24 * 3600 * 1000))
    // 计算出小时数
    let leave1 = usedTime % (24 * 3600 * 1000) // 计算天数后剩余的毫秒数
    let hours = Math.floor(leave1 / (3600 * 1000))
    // 计算相差分钟数
    let leave2 = leave1 % (3600 * 1000) // 计算小时数后剩余的毫秒数
    let minutes = Math.floor(leave2 / (60 * 1000))
    let time = 0
    if (type === 'date') {
      if (days > 0) {
        time = days + '天' + hours + '时' + minutes + '分'
      } else {
        time = hours + '时' + minutes + '分'
      }
    } else {
      time = hours + days * 24 + '时' + minutes + '分'
    }
    return { time: time, days, hours: hours + days * 24, minutes: minutes, minutesCount: hours * 60 * 60 + days * 24 * 60 * 60 + minutes * 60 }
    // return { time: time, hours: (hours + (days * 24)), minutes: minutes, minutesCount: (hours + (days * 24 * 60 * 60)) + (minutes * 60) }
  },
  /**
   * 车牌号
   */
  truckNo(rules, value, callback) {
    let regExp = /(^[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领A-Z]{1}[A-Z]{1}[A-Z0-9]{4}[A-Z0-9挂学警港澳]{1}$)/
    if (!regExp.test(value)) {
      callback(new Error('车牌号不正确'))
      return false
    } else {
      callback()
      return true
    }
  },

  /**
   * 59分钟
   */
  minute(rules, value, callback) {
    let regExp = /^(([0-9])$|([1-5][0-9])$)/
    if (!regExp.test(Number(value))) {
      callback(new Error('不能大于59分钟'))
      return false
    } else {
      callback()
      return true
    }
  },

  /* 判断里程是否大于0 */
  mileage(rule, value, callback) {
    if (Number(value) <= 0) {
      callback(new Error('里程数必须大于0'))
    } else {
      callback()
    }
  },

  // 防抖
  shake(fn, d) {
    let time = null
    return () => {
      if (time) {
        clearTimeout(time)
      }
      time = setTimeout(fn, d)
    }
  },
  // 节流
  throttle(fn, d) {
    let v = true
    return () => {
      if (!v) {
        return false
      }
      v = false
      setTimeout(() => {
        v = true
        fn()
      }, d)
    }
  },
  // 去除前后逗号
  delcomma(str) {
    return str.replace(/^,+/, '').replace(/,+$/, '')
  },

  /**
   * 过滤菜单带有“子节点”菜单
   * @param {*} treeArr  树节点
   * @param {*} disableAll  禁止所有
   * @returns  treeData: 树结构  ids所有树的id del被删除后的id
   */
  filterTree(
    treeArr,
    disableAll = false,
    defaultProps = {
      children: 'children',
      id: 'id',
      label: 'label'
    }
  ) {
    let ids = []
    let delIds = []
    function eachItem(arr) {
      let res = arr.filter((item, key) => {
        if (item[defaultProps.label].indexOf(['子节点']) < 0) {
          ids.push(item[defaultProps.id])
        }
        // else {
        //   delIds.push({ id: item[defaultProps.id], pId: item[defaultProps.id] })
        // }
        if (disableAll) {
          item.disabled = true
        }
        if (item[defaultProps.children] && item[defaultProps.children].length > 0) {
          let child = item[defaultProps.children].filter((item2) => {
            if (item2[defaultProps.label].indexOf(['子节点']) < 0) {
              ids.push(item2[defaultProps.id])
              if (disableAll) {
                item2.disabled = true
              }
              return item2
            } else {
              delIds.push({ id: item2[defaultProps.id], pId: item[defaultProps.id] })
            }
          })
          item[defaultProps.children] = eachItem(child)
        }
        item.key = item[defaultProps.id]
        return item
      })

      return res
    }
    return { treeData: eachItem(treeArr), ids: [...new Set(ids)], delIds: delIds }
  },
  // 属性结构处理
  treeJson({ data, idVal = null, id = 'id', pid = 'pid' }) {
    // console.log('pid', pid)
    // let tree = []
    // 循环迭代解析json

    let itemArr = []
    for (let i = 0; i < data.length; i++) {
      let node = data[i]
      if (node[pid] === '') {
        node[pid] = null
      }
      if (node[pid] === idVal) {
        let newNode = data[i]
        let arr = this.treeJson({ data, idVal: node[id], id: id, pid: pid })
        newNode.children = arr.length > 0 ? arr : null
        itemArr.push(newNode)
      }
    }
    return itemArr
  },
  // 表格合并行处理
  rowColFun({ list, keys = 'id' }) {
    let arr = []
    list.map((item, key) => {
      let firstIndex = list.findIndex((item2) => {
        return item[keys] === item2[keys] // 当id相同的时候，返回第一个相同的Index 赋值给 firstIndex
      })
      if (
        arr.findIndex((item3) => {
          return item3.firstIndex === firstIndex
        }) === -1
      ) {
        arr.push({
          length: list.filter((item4) => {
            return item4[keys] === item[keys] // 利用数组的filter方法，过滤出相同id的数组的长度。数组长度-即为跨多少行
          }).length,
          firstIndex: firstIndex // firstIndex 返回的是第一个id就满足的第一个Index,即为rowIndex开始于第几行。
        })
      }
    })
    return arr
  },
 
  isnumber(val) {
    // 正整数
    // val = val.replace(/[^\d]/g, '')
    // 保留2位小数
    val =
      val
        .replace(/[^\d.]/g, '')
        .replace(/^0+(\d)/, '$1')
        .replace(/^\./, '0.')
        .match(/^\d*(\.?\d{0,2})/g)[0] || ''
    // 第一位0开头，0后面为数字，则过滤掉，取后面的数字
    // 如果输入的第一位为小数点，则替换成 0. 实现自动补全
    // 最终匹配得到结果 以数字开头，只有一个小数点，而且小数点后面只能有0到2位小数
    return val
  },
  browser() {
    let u = navigator.userAgent
    // let app = navigator.appVersion
    // 判断是否IE内核

    return {
      trident: u.indexOf('Trident') > -1, // IE内核

      presto: u.indexOf('Presto') > -1, // opera内核

      webKit: u.indexOf('AppleWebKit') > -1, // 苹果、谷歌内核

      gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') === -1, // 火狐内核

      mobile: !!u.match(/AppleWebKit.*Mobile.*/), // 是否为移动终端

      ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), // ios终端

      android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, // android终端或者uc浏览器

      iPhone: u.indexOf('iPhone') > -1, // 是否为iPhone或者QQHD浏览器

      iPad: u.indexOf('iPad') > -1, // 是否iPad

      webApp: u.indexOf('Safari') === -1, // 是否web应该程序，没有头部与底部

      weixin: u.indexOf('MicroMessenger') > -1, // 是否微信 (2015-01-22新增)

      qq: u.match(/\sQQ/i) === ' qq' // 是否QQ
    }
  },
  // 系统处理
  goPAGE() {
    if (
      navigator.userAgent.match(
        /(phone|pod|iPhone|ios|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
      )
    ) {
      /* window.location.href="你的手机版地址"; */
      if (navigator.userAgent.match(/(iPod|pad|iPad)/i)) {
        return 'pad'
      } else {
        return 'mobile'
      }
    } else {
      /* window.location.href="你的电脑版地址";    */
      return 'pc'
    }
  },
  getUUID() {
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
    var uuid = []
    var i
    var radix = chars.length
    var r

    uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
    for (i = 0; i < 36; i++) {
      if (!uuid[i]) {
        r = 0 | (Math.random() * radix)
        uuid[i] = chars[r]
      }
    }
    return uuid.join('')
  }
  /**
   * 树形数据扁平化
   */
  // treeToFlat(nodes, child = 'childList') {
  //   let result = [];
  //   nodes.forEach(node => {
  //       result.push(node);
  //       if (node[child]) {
  //           result = result.concat(utils.treeToFlat(node[child]));
  //       }
  //   });
  //   return result;
  // }
  //   getPdf ({ id = '#pdf', title = new Date().getTime() }) {
  //     html2Canvas(document.querySelector(id), {
  //       allowTaint: true
  //     }).then(function (canvas) {
  //       let contentWidth = canvas.width
  //       let contentHeight = canvas.height
  //       let pageHeight = contentWidth / 1190.6 * 1683.8
  //       let leftHeight = contentHeight
  //       let position = 0
  //       let imgWidth = 1190.6
  //       let imgHeight = 1190.6 / contentWidth * contentHeight
  //       console.log('d', leftHeight, imgWidth, imgHeight)
  //       let pageData = canvas.toDataURL('image/jpeg', 1.0)
  //       // let img = document.createElement('img')
  //       // img.src = pageData
  //       // document.body.appendChild(img)
  //       let PDF = new JsPDF('', 'pt', 'a2')
  //       if (leftHeight < pageHeight) {
  //         PDF.addImage(pageData, 'JPEG', 0, 0, imgWidth, imgHeight)
  //       } else {
  //         while (leftHeight > 0) {
  //           PDF.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
  //           leftHeight -= pageHeight
  //           position -= 1683.8
  //           if (leftHeight > 0) {
  //             PDF.addPage()
  //           }
  //         }
  //       }
  //       PDF.save(title + '.pdf')
  //     }
  //     )
  //   }
}
export { utils }
